#include <queue>
#include <unistd.h>
#include <pthread.h>

using namespace std;

const int defaultCapcity = 5;    //默认大小

    template<class T>
    class BlockQueue
    {
    //阻塞队列类
    public:
        //初始化容量、互斥锁、条件变量
        BlockQueue(int capacity = defaultCapcity)
            :_capacity(capacity)
        {
            pthread_mutex_init(&_mutex, nullptr);
            pthread_cond_init(&_pcond, nullptr);
            pthread_cond_init(&_ccond, nullptr);
        }

        //销毁互斥锁、条件变量
        ~BlockQueue()
        {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_pcond);
            pthread_cond_destroy(&_ccond);
        }

        //入队列
        void push(const T &in)
        {
            //情况：队列未满，可以继续生产，队列满，需要等待消费

            pthread_mutex_lock(&_mutex);    //互斥

            while(isFull())
            {
                //如果满了，则等待消费
                pthread_cond_wait(&_pcond, &_mutex);
            }

            _que.push(in);  //将数据入队

            pthread_cond_signal(&_ccond);    //同步
            pthread_mutex_unlock(&_mutex);
        }

        //出队列
        void pop(T &out)
        {
            //情况：队列不为空，可以直接消费，队列为空，需要等待生产者生产

            pthread_mutex_lock(&_mutex);    //互斥

            while(isEmpty())
            {
                //如果为空，则等待生产
                pthread_cond_wait(&_ccond, &_mutex);
            }

            //获取数据
            out = _que.front();
            _que.pop();

            pthread_cond_signal(&_pcond);    //同步
            pthread_mutex_unlock(&_mutex);
        }

    private:
        bool isFull() { return _que.size() == _capacity; }
        bool isEmpty() { return _que.empty(); }

    private:
        queue<T> _que;  //队列
        size_t _capacity;   //容量
        pthread_mutex_t _mutex; //互斥锁
        pthread_cond_t _pcond;   //生产者条件变量
        pthread_cond_t _ccond;   //消费者条件变量
    };